package main

import (
	"encoding/json"
	"fmt"
	"github.com/panjf2000/ants/v2"
	"io/ioutil"
	"net/http"
	"sync"
	"time"
)

type User struct {
	ID       int    `json:"id"`
	Name     string `json:"name"`
	Username string `json:"username"`
	Email    string `json:"email"`
	Address  struct {
		Street  string `json:"street"`
		Suite   string `json:"suite"`
		City    string `json:"city"`
		Zipcode string `json:"zipcode"`
	} `json:"address"`
	Phone   string `json:"phone"`
	Website string `json:"website"`
	Company struct {
		Name        string `json:"name"`
		CatchPhrase string `json:"catchPhrase"`
		Bs          string `json:"bs"`
	} `json:"company"`
}

const (
	poolSize   = 5  // 协程池大小
	maxUsers   = 10 //最大用户ID
	apiBaseURL = "https://jsonplaceholder.typicode.com/users/%d"
)

func processUser(userId int, wg *sync.WaitGroup) {
	defer wg.Done()
	// 构建请求URL
	url := fmt.Sprintf(apiBaseURL, userId)
	// 创建带超时的HTTP客户端
	client := &http.Client{Timeout: time.Second * 5}

	// 发送HTTP GET请求
	resp, err := client.Get(url)
	if err != nil {
		fmt.Println(err)
		return
	}

	defer resp.Body.Close()

	// 解析JSON响应
	// 检查状态码

	if resp.StatusCode != http.StatusOK {
		fmt.Printf("请求失败，状态码：%d\n", resp.StatusCode)
		return
	}
	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	var user User
	if err := json.Unmarshal(body, &user); err != nil {
		fmt.Println(err)
		return
	}
	// 打印格式化结果
	fmt.Printf("用户ID：%d\n", user.ID)
	fmt.Printf("用户名：%s\n", user.Username)
	fmt.Printf("邮箱：%s\n", user.Email)
	fmt.Printf("公司名称：%s\n", user.Company.Name)
	// address
	fmt.Printf("地址：%s\n", user.Address.Street)
	fmt.Printf("城市：%s\n", user.Address.City)
	fmt.Printf("邮编：%s\n", user.Address.Zipcode)
	fmt.Printf("公司口号：%s\n", user.Company.CatchPhrase)
	fmt.Printf("公司业务：%s\n", user.Company.Bs)
	// website
	fmt.Printf("网站：%s\n", user.Website)
}
func main() {

	// 创建一个协程池
	pool, _ := ants.NewPool(poolSize)
	defer pool.Release()
	var wg sync.WaitGroup

	// 从1到maxUsers遍历用户ID
	for userID := 1; userID <= maxUsers; userID++ {
		wg.Add(1)
		// 将任务提交到协程池
		err := pool.Submit(func() {
			//processUser(userID, &wg)
			processUserWithClient(userID, &wg)
		})
		// 处理提交错误
		if err != nil {
			wg.Done()
			fmt.Println(err)
		}
	}
	wg.Wait()
	fmt.Println("任务完成")

}

func processUserWithRetry(userID int, wg *sync.WaitGroup) {

}

// 复用 // 在全局创建可复用的客户端
func processUserWithClientWithRetry(userId int, wg *sync.WaitGroup) {
	defer wg.Done()
	url := fmt.Sprintf(apiBaseURL, userId)
	var client = &http.Client{
		Timeout: time.Second * 5,
		Transport: &http.Transport{
			MaxIdleConnsPerHost: poolSize,
		},
	}

	// with retry
	const maxRetry = 3
	resp := &http.Response{}
	for i := 0; i < maxRetry; i++ {
		resp, err := client.Get(url)
		defer resp.Body.Close()
		if err == nil && resp.StatusCode == http.StatusOK {
			break
		}
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	var user User
	if err := json.Unmarshal(body, &user); err != nil {
		fmt.Println(err)
		return
	}

	// 打印格式化结果
	fmt.Printf("用户ID：%d\n", user.ID)
	fmt.Printf("用户名：%s\n", user.Username)
	fmt.Printf("邮箱：%s\n", user.Email)
	fmt.Printf("公司名称：%s\n", user.Company.Name)
	// address
	fmt.Printf("地址：%s\n", user.Address.Street)
	fmt.Printf("城市：%s\n", user.Address.City)
	fmt.Printf("邮编：%s\n", user.Address.Zipcode)
	fmt.Printf("公司口号：%s\n", user.Company.CatchPhrase)
	fmt.Printf("公司业务：%s\n", user.Company.Bs)
	// website
	fmt.Printf("网站：%s\n", user.Website)
}
func processUserWithClient(userId int, wg *sync.WaitGroup) {
	defer wg.Done()
	url := fmt.Sprintf(apiBaseURL, userId)
	var client = &http.Client{
		Timeout: time.Second * 5,
		Transport: &http.Transport{
			MaxIdleConnsPerHost: poolSize,
		},
	}

	resp, err := client.Get(url)
	if err != nil {
		fmt.Println(err)
		return
	}

	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		fmt.Printf("请求失败，状态码：%d\n", resp.StatusCode)
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	var user User
	if err := json.Unmarshal(body, &user); err != nil {
		fmt.Println(err)
		return
	}

	// 打印格式化结果
	fmt.Printf("用户ID：%d\n", user.ID)
	fmt.Printf("用户名：%s\n", user.Username)
	fmt.Printf("邮箱：%s\n", user.Email)
	fmt.Printf("公司名称：%s\n", user.Company.Name)
	// address
	fmt.Printf("地址：%s\n", user.Address.Street)
	fmt.Printf("城市：%s\n", user.Address.City)
	fmt.Printf("邮编：%s\n", user.Address.Zipcode)
	fmt.Printf("公司口号：%s\n", user.Company.CatchPhrase)
	fmt.Printf("公司业务：%s\n", user.Company.Bs)
	// website
	fmt.Printf("网站：%s\n", user.Website)
}
